package com.tianlu.store.service.impl;
 
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.google.common.collect.Maps;
import com.tianlu.store.common.*;
import com.tianlu.store.dto.ScoreDetailDTO;
import com.tianlu.store.dto.TeamPerformanceDTO;
import com.tianlu.store.dto.UpdatePasswordDTO;
import com.tianlu.store.entity.ScoreDetail;
import com.tianlu.store.entity.UserInfo;

import com.tianlu.store.mapper.UserInfoMapper;
import com.tianlu.store.service.OrderInfoService;
import com.tianlu.store.service.ScoreDetailService;
import com.tianlu.store.service.UserInfoService;
import com.tianlu.store.utils.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.Serializable;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @Author 梁东烂
 * @Desc 用户表(UserInfo)表服务实现类
 * @Date 2023-04-01 17:28:49
 */
@Service("userInfoService")
public class UserInfoServiceImpl extends MyBaseServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {
    @Resource
    ScoreDetailService scoreDetailService;
    @Resource
    OrderInfoService orderInfoService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean save(UserInfo userInfo) {
        UserInfo query = new UserInfo();
        query.setPhone(userInfo.getPhone());
        List<UserInfo> dbList = dao.findList(query);
        if (CollUtil.isNotEmpty(dbList)) {
            throw new ServiceException(ResultCode.CODE_400, "手机号已存在！");
        }
        userInfo.setScore(BigDecimal.ZERO);
        return super.save(userInfo);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateById(UserInfo userInfo) {
        UserInfo dbUserInfo = super.getById(userInfo.getId());
        if (Objects.isNull(dbUserInfo)) {
            throw new ServiceException(ResultCode.CODE_400, "用户不存在！");
        }

        // 积分余额有变动需要记录积分明细
        if (dbUserInfo.getScore().compareTo(userInfo.getScore()) != 0) {
            ScoreDetail scoreDetail = new ScoreDetail();
            scoreDetail.setId(IdGen.snowflakeId());
            scoreDetail.setUserId(userInfo.getId());
            scoreDetail.setChangeScore(userInfo.getScore().subtract(dbUserInfo.getScore()));
            scoreDetail.setAfterScore(userInfo.getScore());
            scoreDetail.setCreateTime(new Date());
            scoreDetail.setCreateBy(JwtUtils.getIdByJwtToken());
            scoreDetail.setRemark(StrUtil.isBlank(userInfo.getMsg()) ? "管理员修改" : userInfo.getMsg());
            scoreDetailService.save(scoreDetail);
        }

        return super.updateById(userInfo);
    }

    /**
     * 修改余额
     *
     * @param id    用户id
     * @param score 积分余额
     * @author liangdl
     * @since 2023/4/4 10:37
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateScore(Long id, BigDecimal score) {
        dao.updateScore(id, score);
    }

    @Override
    public List<UserInfo> findGroupTree(Long id) {
        List<UserInfo> userInfoList =  dao.findGroupTree(id);
        return TreeMenuUtil.treeOut(userInfoList, UserInfo::getId, UserInfo::getParentId, UserInfo::getChildren);
    }

    @Override
    public UserInfo getByPhone(String phone) {
        return dao.getByPhone(phone);
    }

    @Override
    public UserInfo getByCode(String code) {
        return dao.getByCode(code);
    }

    @Override
    public UserInfo wxLogin(String code) {
        String openId = WxUtils.getOpenId(code);
        if (StrUtil.isBlank(openId)) {
            throw new ServiceException(ResultCode.USER_LOGIN_FAIL);
        }
        UserInfo userInfo = dao.getByOpenId(openId);
        if (Objects.isNull(userInfo)) {
            userInfo = new UserInfo();
            userInfo.setOpenId(openId);
            return userInfo;
        }

        if (userInfo.getStatus() == 0) {
            throw new ServiceException(ResultCode.USER_ACCOUNT_DISABLE);
        }

        String jwtToken = JwtUtils.getJwtToken(userInfo.getId(), userInfo.getOpenId(), userInfo.getName(), userInfo.getPhone(), userInfo.getStatus(), userInfo.getLevel());
        RedisTemplateUtils.set(Constant.USER_TOKEN_PREFIX + jwtToken, jwtToken, Constant.USER_LOGIN_TOKEN_TIME);
        userInfo.setOpenId(openId);
        userInfo.setToken(jwtToken);
        return userInfo;
    }

    @Override
    public String getPhoneNumber(String code) {
        return WxUtils.getPhoneNumber(code);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public UserInfo signUp(UserInfo userInfo) {
        UserInfo dbUserInfo = dao.getByOpenId(userInfo.getOpenId());
        if (Objects.nonNull(dbUserInfo)) {
            throw new ServiceException(ResultCode.USER_ACCOUNT_ALREADY_EXIST);
        }

        if (Objects.nonNull(userInfo.getParentId())) {
            UserInfo parent = super.getById(userInfo.getParentId());
            if (Objects.isNull(parent)) {
                throw new ServiceException(ResultCode.CODE_400, "邀请人不存在！");
            }
            userInfo.setParentIds(parent.getParentIds() + "," + parent.getId());
        }

//        // 处理用户头像
//        if (StrUtil.isNotEmpty(userInfo.getAvatar())) {
//            String path = CosFileUtils.uploadByPath(userInfo.getAvatar());
//            userInfo.setAvatar(path);
//        }

        // 用户编码
        String maxCode = dao.getMaxCode();
        int num = Integer.parseInt(maxCode.substring(2));
        userInfo.setCode("TL" + String.format("%05d", num + 1));

        userInfo.setSignTime(new Date());
        userInfo.setScore(BigDecimal.ZERO);
        userInfo.setStatus(1);
        userInfo.setLevel(1);
        super.save(userInfo);

        String jwtToken = JwtUtils.getJwtToken(userInfo.getId(), userInfo.getOpenId(), userInfo.getName(), userInfo.getPhone(), userInfo.getStatus(), userInfo.getLevel());
        RedisTemplateUtils.set(Constant.USER_TOKEN_PREFIX + jwtToken, jwtToken, Constant.USER_LOGIN_TOKEN_TIME);
        userInfo.setToken(jwtToken);
        return userInfo;
    }

    @Override
    public List<UserInfo> findByIds(String ids) {
        return dao.findByIds(ids);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void giveScore(Long userId, Long receiveId, BigDecimal score) {
        UserInfo userInfo = super.getById(userId);
        UserInfo receiveUser = super.getById(receiveId);

        if (Objects.isNull(userInfo) || Objects.isNull(receiveUser)) {
            log.error("用户不存在！");
            throw new ServiceException(ResultCode.CODE_400);
        }

        if (userInfo.getScore().compareTo(score) < 0) {
            throw new ServiceException(ResultCode.CODE_400, "余额不足，请联系管理员充值！");
        }

        // 扣减余额，并记录积分明细
        dao.updateScore(userId, userInfo.getScore().subtract(score));
        ScoreDetail scoreDetail = new ScoreDetail();
        scoreDetail.setId(IdGen.snowflakeId());
        scoreDetail.setUserId(userId);
        scoreDetail.setChangeScore(score.multiply(BigDecimal.valueOf(-1)));
        scoreDetail.setAfterScore(userInfo.getScore().subtract(score));
        scoreDetail.setCreateTime(new Date());
        scoreDetail.setCreateBy(0L);
        scoreDetail.setRemark("积分转增扣减");
        scoreDetailService.save(scoreDetail);

        // 接收余额，并记录积分明细
        dao.updateScore(receiveId, receiveUser.getScore().add(score));
        scoreDetail.setId(IdGen.snowflakeId());
        scoreDetail.setUserId(receiveId);
        scoreDetail.setChangeScore(score);
        scoreDetail.setAfterScore(receiveUser.getScore().add(score));
        scoreDetail.setCreateTime(new Date());
        scoreDetail.setCreateBy(0L);
        scoreDetail.setRemark("积分转增");
        scoreDetailService.save(scoreDetail);
    }

    @Override
    public void resettingFreeFlag() {
        dao.resettingFreeFlag();
    }

    @Override
    public List<ScoreDetailDTO> findScoreDetail(Long userId) {
        ScoreDetail detailQuery = new ScoreDetail();
        detailQuery.setUserId(userId);
        List<ScoreDetail> scoreDetailList = scoreDetailService.findList(detailQuery);
        if (CollUtil.isEmpty(scoreDetailList)) {
            return new ArrayList<>(0);
        }
        Map<String, List<ScoreDetail>> resultMap = Maps.newHashMap();
        for (ScoreDetail detail : scoreDetailList) {
            SimpleDateFormat format = new SimpleDateFormat("yyyy/MM");
            String createTime = format.format(detail.getCreateTime());
            List<ScoreDetail> detailList = resultMap.get(createTime);
            if (CollUtil.isEmpty(detailList)) {
                detailList = new ArrayList<>();
            }
            detailList.add(detail);
            resultMap.put(createTime, detailList);
        }

        Map<String, List<ScoreDetail>> result = new LinkedHashMap<>();
        resultMap.entrySet().stream().sorted(Collections.reverseOrder(Map.Entry.comparingByKey())).forEachOrdered(x -> result.put(x.getKey(), x.getValue()));

        List<ScoreDetailDTO> dtoList = new ArrayList<>();
        for (Map.Entry<String, List<ScoreDetail>> entry : result.entrySet()) {
            ScoreDetailDTO dto = new ScoreDetailDTO();
            dto.setMonth(entry.getKey());
            dto.setValue(entry.getValue());
            dtoList.add(dto);
        }
        return dtoList;
    }

    @Override
    public List<TeamPerformanceDTO> findPerformanceDetail(Long userId) {
        // 查询团队成员
        List<Long> members = dao.findTeamMembers(userId);
        if (CollUtil.isEmpty(members)) {
            return new ArrayList<>(0);
        }
        return orderInfoService.findPerformanceDetail(members);
    }

    @Override
    public List<UserInfo> findTeamMembers(Long id) {
        List<UserInfo> userInfoList =  dao.findTeamMemberList(id);
        return TreeMenuUtil.treeOut(userInfoList, UserInfo::getId, UserInfo::getParentId, UserInfo::getChildren);
    }

    @Override
    public Boolean updatePassword(UpdatePasswordDTO updatePasswordDTO) {
        UserInfo userInfo = dao.getByPhone(updatePasswordDTO.getPhone());
        if (Objects.isNull(userInfo)) {
            throw new ServiceException(ResultCode.CODE_400, "账号不存在！");
        }
        if (!updatePasswordDTO.getOldPassword().equals(userInfo.getPassword())) {
            throw new ServiceException(ResultCode.CODE_400, "密码错误");
        }
        userInfo.setPassword(updatePasswordDTO.getNewPassword());
        dao.updateById(userInfo);
        return true;
    }

    @Override
    public UserInfo getById(Serializable id) {
        UserInfo userInfo = super.getById(id);

        if (StrUtil.isBlank(userInfo.getCodePath())) {
            // 生成小程序码
            userInfo.setCodePath(WxUtils.getUnlimitedQRCode(userInfo.getId()));
            super.updateById(userInfo);
        }

        // 查询团队成员
        List<Long> members = dao.findTeamMembers(id);

        if (CollUtil.isEmpty(members)) {
            userInfo.setTeamMembers(0);
            userInfo.setTeamPerformance(BigDecimal.ZERO);
        } else {
            userInfo.setTeamMembers(members.size());
            // 查询团队业绩
            BigDecimal performance = orderInfoService.findTeamPerformance(members);
            userInfo.setTeamPerformance(performance);
        }

        return userInfo;
    }

    @Override
    public List<UserInfo> findList(UserInfo userInfo) {
        List<UserInfo> userList = super.findList(userInfo);
        for (UserInfo info : userList) {
            // 查询团队成员
            List<Long> members = dao.findTeamMembers(info.getId());

            if (CollUtil.isEmpty(members)) {
                info.setTeamMembers(0);
                info.setTeamPerformance(BigDecimal.ZERO);
            } else {
                info.setTeamMembers(members.size());
                // 查询团队业绩
                BigDecimal performance = orderInfoService.findTeamPerformance(members);
                info.setTeamPerformance(performance);
            }
        }
        return userList;
    }
}
